Skip to content

crypto: fix TLSWrap use-after-free on pending write#62967

Closed
alexkozy wants to merge 1 commit intonodejs:mainfrom
alexkozy:fix-tlswrap-destroy-uaf
Closed

crypto: fix TLSWrap use-after-free on pending write#62967
alexkozy wants to merge 1 commit intonodejs:mainfrom
alexkozy:fix-tlswrap-destroy-uaf

Conversation

@alexkozy
Copy link
Copy Markdown
Member

@alexkozy alexkozy commented Apr 26, 2026

Description

Fix use-after-free in TLSWrap::Destroy() when an underlying stream write is still in flight.

EncOut() passes pointers from the enc_out_ BIO internal buffer to the underlying stream's uv_write(). write_size_ is non-zero while that write is in flight. Calling ssl_.reset() frees the SSL context and its BIOs, turning those pointers into dangling references. When libuv completes the write it accesses freed memory (SIGSEGV).

This change:

  • Uses ssl_.release() instead of ssl_.reset() when write_size_ != 0 so the BIO data stays alive for the in-flight uv_write. This is a bounded leak (one SSL context per socket destroyed with in-flight writes) that prevents a segfault.
  • Moves RemoveStreamListener() before SSL cleanup so the underlying stream cannot call back into the TLSWrap after its SSL state is gone.

Test plan

  • python3 tools/test.py --mode=release test/parallel/test-tls-destroy-ssl-with-pending-write test/parallel/test-tls-destroy-whilst-write test/parallel/test-tls-socket-destroy test/parallel/test-tls-transport-destroy-after-own-gc

@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/crypto

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. crypto Issues and PRs related to the crypto subsystem. needs-ci PRs that need a full CI run. labels Apr 26, 2026
EncOut() passes pointers from the enc_out_ BIO internal buffer to the
underlying stream's uv_write().  write_size_ is non-zero while that
write is in flight.  Calling ssl_.reset() frees the SSL context and
its BIOs, turning those pointers into dangling references.  When libuv
completes the write it accesses freed memory (SIGSEGV).

Use ssl_.release() instead of ssl_.reset() when write_size_ != 0 so
the BIO data stays alive for the in-flight uv_write.  This is a
bounded leak (one SSL context per socket destroyed with in-flight
writes) that prevents a segfault.

Also move RemoveStreamListener() before SSL cleanup so the underlying
stream cannot call back into the TLSWrap after its SSL state is gone.

Refs: nodejs#62393
Made-with: Cursor
@alexkozy alexkozy force-pushed the fix-tlswrap-destroy-uaf branch from c23571f to afcee0e Compare April 26, 2026 04:36
@alexkozy
Copy link
Copy Markdown
Member Author

Opened this one by accident; I should open an issue instead, since the fix here works, but it leaks the bio data structure.

@alexkozy alexkozy closed this Apr 26, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.66%. Comparing base (0f68423) to head (afcee0e).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #62967      +/-   ##
==========================================
- Coverage   91.49%   89.66%   -1.83%     
==========================================
  Files         356      706     +350     
  Lines      150784   219397   +68613     
  Branches    23768    42062   +18294     
==========================================
+ Hits       137955   196730   +58775     
- Misses      12557    14593    +2036     
- Partials      272     8074    +7802     
Files with missing lines Coverage Δ
src/crypto/crypto_tls.cc 78.19% <100.00%> (ø)

... and 470 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Issues and PRs that require attention from people who are familiar with C++. crypto Issues and PRs related to the crypto subsystem. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants